package com.alex.utils;

import cn.hutool.core.collection.ConcurrentHashSet;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ZipUtil;
import cn.hutool.db.Db;
import cn.hutool.db.Entity;
import com.alibaba.fastjson.JSONObject;
import lombok.Data;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class OftenUtils {

    // 取小数点后4位
    public static double takeFourDigits(double d) {
        BigDecimal bd = new BigDecimal(d);
        BigDecimal bd2 = bd.setScale(4, RoundingMode.HALF_UP);
        return Double.parseDouble(bd2.toString());
    }

    // 对Map进行排序，Integer类型，目前仅返回前len条.limit(len)，且Map的Key的值不能是notStr。
    public static Map<String, Integer> mapSortValueNotStr(Map<String, Integer> mapName, String notStr, Integer len) {
        Map<String, Integer> result = new LinkedHashMap<>();
        mapName.entrySet().stream().filter(var -> !var.getKey().equals(notStr)).sorted(Map.Entry.<String, Integer>comparingByValue()
                .reversed()).limit(len).forEachOrdered(e -> result.put(e.getKey(), e.getValue()));
        return result;
    }

    // 两个值进行比较，返回大的那一个，类型Integer。
    public static Integer getMaxIntValue(Integer max_num, Integer num) {
        if (num > max_num) {
            return num;
        }
        return max_num;
    }

    // 两个值进行比较，返回大的那一个，类型Double。
    public static Double getMaxDouValue(Double max_dou, Double dou) {
        if (null == max_dou || null == dou) {
            return 0.0;
        }
        if (dou > max_dou) {
            return dou;
        }
        return max_dou;
    }

    // 获取strDoubleMap值的最大值，类型是Double。
    public static Double getMaxDouValue(Map<String, Double> strDoubleMap) {
        if (null == strDoubleMap) {
            return 0.0;
        }
        double max = 0.0;
        for (Map.Entry<String, Double> entry : strDoubleMap.entrySet()) {
            if (entry.getValue() > max) {
                max = entry.getValue();
            }
        }
        return max;
    }

    // 获取strIntMap值的最大值，类型是Integer。
    public static Integer getMaxIntValue(Map<String, Integer> strIntMap) {
        if (null == strIntMap) {
            return 0;
        }
        Integer max = 0;
        for (Map.Entry<String, Integer> entry : strIntMap.entrySet()) {
            if (entry.getValue() > max) {
                max = entry.getValue();
            }
        }
        return max;
    }

    // 字符串转Double，整形的或小数类型的，都可以转。
    public static Double strToDouble(String str) {
        if (null == str) {
            return 0.0;
        }
        double dou = 0.0;
        if (NumberUtil.isInteger(str)) {
            dou = 0.0 + Double.parseDouble(str);
        }
        if (NumberUtil.isDouble(str)) {
            dou = 0.0 + Double.parseDouble(str);
        }
        return dou;
    }

    // 字符串转Integer，整形的或小数类型的，都可以转。1.95会转为1，这里没有作四舍五入。
    public static Integer strToInteger(String str) {
        if (null == str) {
            return 0;
        }
        int num = 0;
        if (NumberUtil.isInteger(str)) {
            num = Integer.parseInt(str);
        }
        if (NumberUtil.isDouble(str)) {
            num = (int) Double.parseDouble(str);
        }
        return num;
    }

    // 字符串转换为List后输出，参数len是对字符串长度的约束，一般来说List存表后的字符串应大于4位，比如：["图书馆"]
    public static List<String> strToList(String str) {
        if (str.length() > 1) {
            try {
                List<String> list = JSONObject.parseArray(str, String.class);
                if (null != list && list.size() > 0) {
                    return list;
                }
            } catch (Exception e) {
                System.out.println("\033[31;1m" + "--strToList err-- " + "\033[0m" + str);
            }
        }
        return new ArrayList<>();
    }

    /**
     * 以下是旧的_DEPTLIST_220621
     */
    public static List<String> strToList(String str, Integer time) {
        if (str.length() > 1) {
            ArrayList<String> objects = new ArrayList<>();
            objects.add(str);
            return new ArrayList<>(objects);
        }
        return new ArrayList<>();
    }

    // 字符串转Map，要求原数据必须为Map类型，因为存表或其它转成了String，现在再转为Map，键和值均为String。
    public static Map<String, String> strToMap(String str) {
        Map<String, String> result = new HashMap<>();
        if (null == str || str.length() < 7) {
            return result;
        }
        try {
            Map map = JSONObject.parseObject(str, Map.class);
            map.forEach((k, v) -> {
                result.put(k.toString().trim(), v.toString().trim());
            });
        } catch (Exception e) {
            System.out.println("\033[31;1m" + "--strToMap err-- " + "\033[0m" + str);
        }
        return result;
    }

    // 如果Map中存在id，则返回id的值，否则返回0.0。
    public static Double getMapValue(Map<Integer, Double> intDouMap, Integer id) {
        if (intDouMap.containsKey(id)) {
            return intDouMap.get(id);
        }
        return 0.0;
    }

    // 返回Double类型的字段的值，field为字段的名称。
    public static Double getDouField(Entity entry, String field) {
        if (null != entry) {
            Double dou = entry.getDouble(field);
            if (null != dou && dou > 0.0) {
                return dou;
            }
        }
        return 0.0;
    }

    // 返回Integer类型的字段的值，field为字段的名称。
    public static Integer getIntField(Entity entry, String field) {
        if (null != entry) {
            Integer num = entry.getInt(field);
            if (null != num && num > 0) {
                return num;
            }
        }
        return 0;
    }

    // 返回String类型的字段的值，field为字段的名称。
    public static String getStrField(Entity entry, String field) {
        if (null != entry) {
            String str = entry.getStr(field);
            if (StringUtil.isNotNull(str)) {
                return str.trim();
            }
        }
        return "";
    }

    // 返回Byte类型的字段的值，field为字段的名称。
    public static String getByteField(Entity entry, String field) {
        if (null != entry) {
            byte[] bytes = ZipUtil.unGzip(entry.getBytes(field));
            String str = new String(bytes, StandardCharsets.UTF_8);
            if (str.length() > 0) {
                return str.trim();
            }
        }
        return "";
    }

    // 字符串转Map，要求原数据必须为Map类型，因为存表或其它转成了String，现在再转为Map，键为String和值为List<String>。
    public static Map<String, List<String>> strToMapList(String str) {
        Map<String, List<String>> result = new HashMap<>();
        if (null == str || str.length() < 7) {
            return result;
        }
        try {
            Map map = JSONObject.parseObject(str, Map.class);
            map.forEach((k, v) -> {
                result.put(k.toString().trim(), strToList(v.toString().trim()));
            });
        } catch (Exception e) {
            System.out.println("\033[31;1m" + "--strToMapList err-- " + "\033[0m" + str);
        }
        return result;
    }

    // 获取现在年，方法是当前时间戳减去8个月后再取年，即2021年7月1日是2021年，2021年6月1日是2020年。此用于新词发现，最长的比较就是一年半与之前的所有相比。
    public static Integer getNowYear() {
        long time = System.currentTimeMillis() - 60 * 60 * 24 * 30 * 6 * 1000L;
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
        String format = sdf.format(new Date(time));
        if (NumberUtil.isInteger(format)) {
            return Integer.parseInt(format);
        }
        return 1900;
    }

    // 打印申请的内存
    public static void printMemory() {
        String freeMemory = Runtime.getRuntime().freeMemory() / 1024 / 1024 / 1024 + " Gb";
        String totalMemory = Runtime.getRuntime().totalMemory() / 1024 / 1024 / 1024 + " Gb";
        String maxMemory = Runtime.getRuntime().maxMemory() / 1024 / 1024 / 1024 + " Gb";
        System.out.println("当前能够申请到的最大内存--" + maxMemory + "--当前空余 " + freeMemory + "--已经从操作系统获取的内存--" + totalMemory);
    }

    // 插入这类的Map：主键为String，值为Set，且为Integer类型，一般为id号的集合。
    public static void putStrSetInt(String str, Integer id, Map<String, Set<Integer>> strSetIntMap) {
        strSetIntMap.compute(str, (k, v) -> {
            if (v == null) {
                v = new ConcurrentHashSet<>();
            }
            v.add(id);
            return v;
        });
    }

    // 插入这类的Map：主键为String，值为Map，且为Integer类型，一般用于保存某个类型（比如基金或单位）下的某个名称总共出现的次数。
    public static void putStrStrInt(String type, String name, Map<String, Map<String, Integer>> strStrIntMap) {
        strStrIntMap.compute(type, (k, v) -> {
            if (v == null) {
                v = new ConcurrentHashMap<>();
            }
            v.compute(name, (key, value) -> value != null ? (value + 1) : 1);
            return v;
        });
    }

    // 插入这类的Map：主键为String，值为Map，且为Double类型，一般用于保存某个类型（比如基金或单位）下的某个名称的得分。
    public static void putStrStrDou(String type, String name, Map<String, Map<String, Double>> strStrIntMap, Double score) {
        strStrIntMap.compute(type, (k, v) -> {
            if (v == null) {
                v = new ConcurrentHashMap<>();
            }
            v.put(name, score);
            return v;
        });
    }

    // 插入这类的Map：主键为Integer，值为Map，且为Set<String>类型，一般用于保存某个长度的关键词的集合。
    public static void putIntStrSetStr(Integer len, String name, Map<Integer, Map<String, Set<String>>> intStrIntMap, String value) {
        intStrIntMap.compute(len, (k, v) -> {
            if (v == null) {
                v = new ConcurrentHashMap<>();
            }
            v.compute(name, (k2, v2) -> {
                if (v2 == null) {
                    v2 = new ConcurrentHashSet<>();
                }
                v2.add(value);
                return v2;
            });
            return v;
        });
    }

    // 插入这类的Map：主键为List<String>，值为Set<Integer>，且为Integer类型，一般用于保存共词A和B，共同出现的论文ID号集合。
    public static void putListStrListInt(List<String> type, Integer id, Map<List<String>, Set<Integer>> listStrListIntMap) {
        listStrListIntMap.compute(type, (k, v) -> {
            if (v == null) {
                v = new ConcurrentHashSet<>();
            }
            v.add(id);
            return v;
        });
    }

    // 插入这类的Map：主键为String，名称为String，值为List，且为Double类型。比如，插入用于计算单位或基金的篇均被引次数。
    public static void putStrStrListDou(Map<String, Map<String, List<Double>>> strStrListIntMap, String key, String name, Double value) {
        strStrListIntMap.compute(key, (k, v) -> {
            if (v == null) {
                v = new ConcurrentHashMap<>();
            }
            v.compute(name, (k1, v1) -> {
                if (v1 == null) {
                    v1 = Collections.synchronizedList(new ArrayList<>());
                }
                v1.add(value);
                return v1;
            });
            return v;
        });
    }

    // 插入这类的Map：主键为String，值为List，且为Integer类型，一般插入某个关键词就分布在哪些文章id中的集合。
    public static void putStrListInt(Map<String, List<Integer>> strListIntMap, String str, Integer id) {
        strListIntMap.compute(str, (k, v) -> {
            if (v == null) {
                v = Collections.synchronizedList(new ArrayList<Integer>());
            }
            v.add(id);
            return v;
        });
    }

    // 插入这类的Map：主键为String，值为List，且为String类型。
    public static void putStrListStr(Map<String, List<String>> strListStrMap, String name, String list) {
        strListStrMap.compute(name, (k, v) -> {
            if (v == null) {
                v = Collections.synchronizedList(new ArrayList<String>());
            }
            v.add(list);
            return v;
        });
    }

    // 插入这类的Map：主键为Integer，值为List，且为Integer类型，一般插入某年就分布在哪些文章id中的集合。
    public static void putIntListInt(Map<Integer, List<Integer>> intListIntMap, Integer year, Integer id) {
        intListIntMap.compute(year, (k, v) -> {
            if (v == null) {
                v = Collections.synchronizedList(new ArrayList<Integer>());
            }
            v.add(id);
            return v;
        });
    }

    // 插入这类的Map：主键为Integer，值为Set，且为String类型，一般主键为id号相对应的集合。
    public static void putIntSetStr(Integer id, String str, Map<Integer, Set<String>> intSetStrMap) {
        intSetStrMap.compute(id, (k, v) -> {
            if (v == null) {
                v = new ConcurrentHashSet<>();
            }
            v.add(str);
            return v;
        });
    }

    // 插入这类的Map：主键为String，值为Set，且为String类型，一般保存比如某个单位下作者的集合。
    public static void putStrSetStr(String name, String str, Map<String, Set<String>> strSetStrMap) {
        strSetStrMap.compute(name, (k, v) -> {
            if (v == null) {
                v = new ConcurrentHashSet<>();
            }
            v.add(str);
            return v;
        });
    }

    // 判断是否包含中文汉字
    public static boolean isContainChinese(String str) {
        Pattern p = Pattern.compile("[\u4e00-\u9fa5]");
        Matcher m = p.matcher(str);
        return m.find();
    }

    // 对Map根据Key进行排序，此排序为最大的在前面，Integer, Integer类型
    public static Map<Integer, Integer> mapSortByKeyInt(Map<Integer, Integer> map) {
        Map<Integer, Integer> result = new LinkedHashMap<>(map.size());
        map.entrySet().stream().sorted(Map.Entry.<Integer, Integer>comparingByKey().reversed()).forEachOrdered(e -> result.put(e.getKey(), e.getValue()));
        return result;
    }

    // 对Map根据Key进行排序，此排序为最大的在前面，Integer, List<Integer>类型
    public static Map<Integer, List<Integer>> mapSortByKeyListInt(Map<Integer, List<Integer>> map) {
        Map<Integer, List<Integer>> result = new LinkedHashMap<>(map.size());
        map.entrySet().stream().sorted(Map.Entry.<Integer, List<Integer>>comparingByKey().reversed()).forEachOrdered(e -> result.put(e.getKey(), e.getValue()));
        return result;
    }

    // 对Map进行排序，此排序为最大的在前面，输入一个map，再返回一个排序后的新map，Integer, Integer类型
    public static Map<Integer, Integer> mapSortValueInt(Map<Integer, Integer> mapName) {
        Map<Integer, Integer> result = new LinkedHashMap<>();
        mapName.entrySet().stream()
                .sorted(Map.Entry.<Integer, Integer>comparingByValue().reversed())
                .forEachOrdered(e -> result.put(e.getKey(), e.getValue()));
        return result;
    }

    // 对Map进行排序，此排序为最大的在前面，输入一个map，再返回一个排序后的新map，Integer, Integer类型
    public static Map<Integer, Double> mapSortValueDou(Map<Integer, Double> mapName) {
        Map<Integer, Double> result = new LinkedHashMap<>();
        mapName.entrySet().stream()
                .sorted(Map.Entry.<Integer, Double>comparingByValue().reversed())
                .forEachOrdered(e -> result.put(e.getKey(), e.getValue()));
        return result;
    }

    // 返回指定字段的值
    public static String getFieldValue(Entity entry, String field, Integer len) {
        String str = entry.getStr(field);
        if (null == str) {
            return "";
        }
        str = str.trim();
        if (str.length() > len) {
            return str;
        }
        return "";
    }





    // 把两个字符串加入list，再对list进行默认排序后返回。
    public static List<String> sortList(String a, String b) {
        List<String> list = new ArrayList<>();
        list.add(a);
        list.add(b);
        Collections.sort(list);
        return list;
    }

    // 对Map进行排序，此排序为最大的在前面，输入一个map，再返回一个排序后的新map，String, Double类型
    public static Map<String, Double> mapSortValue(Map<String, Double> mapName) {
        Map<String, Double> result = new LinkedHashMap<>();
        mapName.entrySet().stream()
                .sorted(Map.Entry.<String, Double>comparingByValue()
                        .reversed()).forEachOrdered(e -> result.put(e.getKey(), e.getValue()));
        return result;
    }

    // 对Map进行排序，此排序为最大的在前面，输入一个map，再返回一个排序后的新map，String, Double类型，本排序增加了过滤功能，可以设置要前多少（len）个。
    public static Map<String, Double> mapSortValueDouLen(Map<String, Double> mapName, Integer len) {
        Map<String, Double> result = new LinkedHashMap<>();
        mapName.entrySet().stream()
                .sorted(Map.Entry.<String, Double>comparingByValue()
                        .reversed()).limit(len).forEachOrdered(e -> result.put(e.getKey(), e.getValue()));
        return result;
    }

    // 对Map进行排序，此排序为最大的在前面，输入一个map，再返回一个排序后的新map，Integer, Integer类型，本排序增加了过滤功能，可以设置要前多少（len）个。
    public static Map<Integer, Integer> mapSortValueLen(Map<Integer, Integer> mapName, Integer len) {
        Map<Integer, Integer> result = new LinkedHashMap<>();
        mapName.entrySet().stream()
                .sorted(Map.Entry.<Integer, Integer>comparingByValue()
                        .reversed()).limit(len).forEachOrdered(e -> result.put(e.getKey(), e.getValue()));
        return result;
    }

    // 对Map进行排序，此排序为最大的在前面，输入一个map，再返回一个排序后的新map，Integer, Integer类型，本排序增加了过滤功能，可以设置要前多少（len）个。
    public static Map<Integer, Double> mapSortValueLenDouble(Map<Integer, Double> mapName, Integer len) {
        Map<Integer, Double> result = new LinkedHashMap<>();
        mapName.entrySet().stream()
                .sorted(Map.Entry.<Integer, Double>comparingByValue()
                        .reversed()).limit(len).forEachOrdered(e -> result.put(e.getKey(), e.getValue()));
        return result;
    }

    // 对Map进行排序，此排序为最大的在前面，输入一个map，再返回一个排序后的新map，String, Integer类型，本排序增加了过滤功能，可以设置要前多少（len）个。
    public static Map<String, Integer> mapSortValueIntLen(Map<String, Integer> mapName, Integer len) {
        Map<String, Integer> result = new LinkedHashMap<>();
        mapName.entrySet().stream()
                .sorted(Map.Entry.<String, Integer>comparingByValue()
                        .reversed()).limit(len).forEachOrdered(e -> result.put(e.getKey(), e.getValue()));
        return result;
    }

    // 修改乱字符  java.sql.SQLException: Incorrect string value: '\xF0\x9D\x99\xB8 b...' for column 'figure' at row 1
    public static String emojiConvert(String str) {
        StringBuffer sb = new StringBuffer();
        String patternString = "([\\x{10000}-\\x{10ffff}\ud800-\udfff])";
        try {
            Pattern pattern = Pattern.compile(patternString);
            Matcher matcher = pattern.matcher(str);
            while (matcher.find()) {
                try {
                    matcher.appendReplacement(sb, "[[" + URLEncoder.encode(matcher.group(1), "UTF-8") + "]]");
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
            }
            matcher.appendTail(sb);
        } catch (Exception e) {
            System.out.println("出错的STR:" + str);
        }
        return sb.toString();
    }

    //字符串排序
    public static String strSort(String str) {
        char[] s1 = str.toCharArray();
        for (int i = 0; i < s1.length; i++) {
            for (int j = 0; j < i; j++) {
                if (s1[i] < s1[j]) {
                    char temp = s1[i];
                    s1[i] = s1[j];
                    s1[j] = temp;
                }
            }
        }
        String st = new String(s1);
        return st;
    }

    //获取两字符串的相似度_1
    public static double getSimilarityRatio(String str, String target) {
        int max = Math.max(str.length(), target.length());
        return 1 - (double) compare(str, target) / max;
    }

    //获取两字符串的相似度_2 两字符串相似度计算算法 Levenshtein Distance编辑距离算法
    private static int compare(String str, String target) {
        int d[][];
        int n = str.length();
        int m = target.length();
        int i;
        int j;
        char ch1;
        char ch2;
        int temp;
        if (n == 0) {
            return m;
        }
        if (m == 0) {
            return n;
        }
        d = new int[n + 1][m + 1];
        for (i = 0; i <= n; i++) {
            d[i][0] = i;
        }
        for (j = 0; j <= m; j++) {
            d[0][j] = j;
        }
        for (i = 1; i <= n; i++) {
            ch1 = str.charAt(i - 1);
            for (j = 1; j <= m; j++) {
                ch2 = target.charAt(j - 1);
                if (ch1 == ch2 || ch1 == ch2 + 32 || ch1 + 32 == ch2) {
                    temp = 0;
                } else {
                    temp = 1;
                }
                d[i][j] = min(d[i - 1][j] + 1, d[i][j - 1] + 1, d[i - 1][j - 1] + temp);
            }
        }
        return d[n][m];
    }

    //获取两字符串的相似度_3
    private static int min(int one, int two, int three) {
        return (one = Math.min(one, two)) < three ? one : three;
    }

    //并查集算法String类型_1  原来：List<Set<String>> disjointSet(Set<String> set, String s, String spl) 中间的参数是没有使用的。
    public static List<Set<String>> disjointSet(Set<String> set, String spl) {
        List<Set<String>> list = new ArrayList<>();
        List<String> vs = new ArrayList<>(set);
        int SIZE = vs.size();
        String[][] strs = new String[SIZE][];
        for (int i = 0; i < SIZE; i++) {
            strs[i] = vs.get(i).split(spl);
        }
        for (String[] str : strs) {
            Set<String> res = new HashSet<>(Arrays.asList(str));
            list.add(res);
        }
        int[] father = new int[SIZE];
        for (int i = 0; i < SIZE; i++) {
            father[i] = i;
        }
        Map<String, List<Integer>> map = new HashMap<>();
        for (int i = 0; i < SIZE; i++) {
            for (String each : strs[i]) {
                if (!map.containsKey(each)) {
                    List<Integer> li = new ArrayList<>();
                    li.add(i);
                    map.put(each, li);
                } else {
                    map.get(each).add(i);
                }
            }
        }
        for (Map.Entry<String, List<Integer>> entry : map.entrySet()) {
            List<Integer> value = entry.getValue();
            unionHelp(value, father);
        }
        for (int i = 0; i < SIZE; i++) {
            if (i != father[i]) {
                Set<String> dest = list.get(getFather(i, father));
                Set<String> source = list.get(i);
                dest.addAll(source);
            }
        }
        for (int i = 0; i < SIZE; i++) {
            if (i != father[i]) {
                list.get(i).clear();
            }
        }
        list.removeIf(strings -> strings.size() == 0);
        return list;
    }

    //并查集算法String类型_2
    public static void unionHelp(List<Integer> list, int[] father) {
        int minFather = getFather(list.get(0), father);
        for (int i = 0, size = list.size(); i < size; i++) {
            father[getFather(list.get(i), father)] = minFather;
        }
    }

    //并查集算法String类型_3
    public static int getFather(int x, int[] father) {
        while (x != father[x]) {
            x = father[x];
        }
        return x;
    }

    // 增加Set，如果是中文，加入到中文中，如果是英文，加入到英文中。
    public static void addNameSet(String str, Set<String> cnNameSet, Set<String> enNameSet) {

        if (!Objects.equals(str, "☷")) {
            if (str.length() > 1) {
                if (isContainChinese(str)) {
                    cnNameSet.add(str);
                } else {
                    enNameSet.add(str.toLowerCase());
                }
            }
        }
    }

    // 相对精确的加减乘除
    public static class Arith {
        //默认除法运算精度
        private static final int DEF_DIV_SCALE = 6;

        //构造器私有化，让这个类不能实例化
        private Arith() {
        }

        //提供精确的加法运算
        public static double add(double v1, double v2) {
            BigDecimal b1 = BigDecimal.valueOf(v1);
            BigDecimal b2 = BigDecimal.valueOf(v2);
            return b1.add(b2).doubleValue();
        }

        //精确的减法运算
        public static double sub(double v1, double v2) {
            BigDecimal b1 = BigDecimal.valueOf(v1);
            BigDecimal b2 = BigDecimal.valueOf(v2);
            return b1.subtract(b2).doubleValue();
        }

        //精确的乘法运算
        public static double mul(double v1, double v2) {
            BigDecimal b1 = BigDecimal.valueOf(v1);
            BigDecimal b2 = BigDecimal.valueOf(v2);
            return b1.multiply(b2).doubleValue();
        }

        //提供（相对）精确的除法运算，当发生除不尽的情况时，精确到小数点后10位的数字四舍五入
        public static double div(double v1, double v2) {
            BigDecimal b1 = BigDecimal.valueOf(v1);
            BigDecimal b2 = BigDecimal.valueOf(v2);
            return b1.divide(b2, DEF_DIV_SCALE, BigDecimal.ROUND_HALF_UP).doubleValue();
        }
    }

    // 读表分页的方法
    @Data
    public static class PageInfo {
        Integer from;
        Integer to;

        public PageInfo() {
        }

        public PageInfo(Integer from, Integer to) {
            this.from = from;
            this.to = to;
        }
    }


}
